package dashboard;

import java.util.LinkedHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import dashboard.UserRegistry;
import dashboard.CourseRegistry;
import java.util.Date;
import java.util.*;


public class Statistics {


	public Statistics()
	{
	}

	/**
	 * Alle gebruikers die momenteel aan het timen zijn worden opgehaald en in een lijst geplaatst, samen met de activiteit 
	 * waarvoor hij timet.
	 * 
	 * @return LinkedMap met gebruikersnaam als key en activiteit als value van de gebruikers die aan het timen zijn.

	 */
	public static Map<String,Activity> getLiveStudents() 
	{

		Map<String,Activity> busyStudents = new LinkedHashMap<String,Activity>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user: users) {
			if(user.getTimerStatus()){
				busyStudents.put(user.getUserName(),user.getActivities().get(user.getActivities().size()-1));
			}
		}
		return busyStudents;
	}

	/**
	 * Alle activiteiten van dit schooljaar van de opgegeven gebruiker worden in een lijst weergegeven.
	 * 
	 * @param currentUser
	 * @return Lijst met alle activiteiten gedaan dit schooljaar van de huidige gebruiker.
	 * 
	 */
	public static List<Activity> getUserActivities(User currentUser)
	{
		List<Activity> showUserActivities = new ArrayList<Activity>();
		User user = UserRegistry.getInstance().getUser(currentUser.getUserName());
		List<Activity> userActivities = user.getActivities();
		for (Activity activity : userActivities) {
			if (controlYear(activity.getStart())) {
				showUserActivities.add(activity);
			}
		}
		return showUserActivities;
	}

	/**
	 * Alle activiteiten van dit schooljaar van alle gebruikers worden in een lijst weergegeven.
	 * 
	 * @return Lijst met alle activiteiten gedaan dit schooljaar van alle gebruikers.
	 */
	public static List<Activity> getAllUsersActivities()
	{
		List<Activity> allUsersActivities = new ArrayList<Activity>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user: users) {
			allUsersActivities.addAll(getUserActivities(user));
		}
		return allUsersActivities;
	}

	/**
	 * Alle milestones van de opgegeven gebruiker worden onderverdeeld in bereikte, niet bereikte of nog lopende milestones.
	 * Het aantal van elk wordt weergegeven in een map.
	 * 
	 * @param currentUser
	 * @return Map met als key de status van de milestones (bereikt, niet bereikt of bezig) en als value het aantal milestones 
	 * met de overeenkomstige status.
	 */
	public static Map<String, Double> getUserMilestones(User currentUser)
	{
		List<Milestone> userMilestones = new ArrayList<Milestone>();
		List<Milestone> showUserMilestones = new ArrayList<Milestone>();
		Map<String, Double> userMilestonesPerType = new LinkedHashMap<String, Double>();
		User user = UserRegistry.getInstance().getUser(currentUser.getUserName());
		userMilestones = user.getMilestones();
		for (Milestone milestone : userMilestones) {
			if (controlYear(milestone.getStart())) {
				showUserMilestones.add(milestone);
			}
		}
		double unachieved=0.0;
		double achieved=0.0;
		double ongoing =0.0;
		double future = 0.0;
		
		for (Milestone milestone : showUserMilestones){
			Date end = milestone.getEnd();
			Date start = milestone.getStart();
			Date now = new Date();
			if(getProgressMilestone(milestone,user)>=100){
				achieved++;
			}
			else if(now.before(start)) {
				future++;
			}
			else if(now.after(start) && now.before(end)){
				ongoing++;
			}
			else{
				unachieved++;
			}
		}
		userMilestonesPerType.put("achieved milestone", achieved);
		userMilestonesPerType.put("unachieved milestone", unachieved);
		userMilestonesPerType.put("ongoing milestone", ongoing);
		userMilestonesPerType.put("future milestone", future);
		return userMilestonesPerType;
	}

	/**
	 * Alle milestones van alle gebruikers worden onderverdeeld in bereikte, niet bereikte of nog lopende milestones.
	 * Het aantal van elk wordt weergegeven in een map.
	 * 
	 * @return Map met als key de status van de milestones (bereikt, niet bereikt of bezig) en als value het aantal milestones 
	 * met de overeenkomstige status.
	 */
	public static Map<String, Double> getAllUsersMilestones()
	{
		Map<String, Double> allUsersMilestones = new LinkedHashMap<String, Double>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user: users) {
			allUsersMilestones.putAll(getUserMilestones(user));
		}
		return allUsersMilestones;
	}

	/**
	 * Het aantal bereikte milestones van de opgegeven gebruiker.
	 * 
	 * @param currentUser
	 * @return Aantal voltooide milestones van de currentUser.
	 */
	public static double amountOfAchievedMilestones(User currentUser)
	{
		double amount = 0;
		User user = UserRegistry.getInstance().getUser(currentUser.getUserName());
		List<Milestone> userMilestones = user.getMilestones();
		Map<String, Double> amountMap = getUserMilestones(currentUser);
		amount = amountMap.get("achieved milestone");
		return amount;
	}

	/**
	 * Er wordt gecontroleerd of de opgegeven milestone succesvol voltooid is.
	 * 
	 * @param milestone
	 * @param user
	 * @return true indien de milestone succesvol voltooid is, false indien hij niet succesvol voltooid is.
	 * 
	 */
	public static boolean milestoneIsAchieved(Milestone milestone, User user)
	{
		if(getProgressMilestone(milestone, user) == 100.0){
			return true;
		}
		return false;
	}
	
	public static double getProgressMilestone(Milestone milestone, User user)
	{
		Date end = milestone.getEnd();
		Date start = milestone.getStart();
		double total = 0.0;
		List<Long>courseIds = milestone.getCourses();
		List<String> types= milestone.getTypes();
		List<Activity> activities = user.getActivities();
		for(Activity activity : activities){
			if(controlYear(activity.getStart()) && courseIds.contains(activity.getCourseId())
					&& activity.getStart().after(start) && activity.getStart().before(end)
					&& types.contains(activity.getType())){
				if(milestone.getAction().equals("Pages")){
					total = total+activity.getNrOfPages();
				}
				else{
					total=total+activity.getDuration();
					
				}
			}
		}
			if(!milestone.getAction().equals("Pages")){
			total=total/3600;
			}
	
		double result = (total/ (double) milestone.getGoal());
		result = result*100;
		result = Math.round(result);
	
		return result;
	}
	
	public static double getProgressMilestoneTime(Milestone milestone)
	{
		Date now = new Date();
		double result=-1;
		double tussenResult = now.getTime() - milestone.getStart().getTime();
		if(tussenResult>0){
		result = (tussenResult);
		result = result/(milestone.getEnd().getTime() - milestone.getStart().getTime());
		result = result*100;
		result = Math.round(result);
		}
		
		return result;
	}

	
	/**
	 * De maand van een opgegeven datum wordt weergegeven. 0 is Oktober, 1 is November,...,
	 * 3 is Januari, 4 is Februari,..., 11 is September.
	 * 
	 * @param date
	 * @return monthNumber
	 */
	public static int getMonth(Date date)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		if (month>=9){
			month=month-9;
		}
		else {
			month=month+3;
		}
		return month;
	}

	/**
	 * Methode controleert of de opgegeven activiteit binnen het huidige schooljaar valt.
	 * 
	 * @param datum van activiteit
	 * @return true indien de activiteit binnen het huidige schooljaar valt, false indien dit niet het geval is.
	 */
	public static boolean controlYear(Date activity)
	{
		Calendar calendar = Calendar.getInstance();
		Date now = new Date();
		calendar.setTime(now);
		int thisYear = calendar.get(Calendar.YEAR);
		int thisMonth = getMonth(now);
		calendar.setTime(activity);		
		int yearOfActivity = calendar.get(Calendar.YEAR);
		int monthOfActivity = getMonth(activity);
		if (thisYear == yearOfActivity) {
			if (thisMonth < 3 && monthOfActivity < 3) {
				return true;
			}
			if (thisMonth >= 3 && monthOfActivity >= 3) {
				return true;
			}
		}
		if(thisYear == yearOfActivity+1 && monthOfActivity < 3) {
			return true;
		}
		return false;
	}

	/**
	 * De activiteiten van de opgegeven gebruiker in een opgegeven maand worden weergegeven in een lijst.
	 * 
	 * @param currentUser
	 * @param monthNumber (rekening houden met oktober is 0, november 1, ..., september 11)
	 * @return Lijst met de activiteiten van de currentUser van de opgegeven maand.
	 */
	public static List<Activity> getMonthlyActivitiesUser(User currentUser, int month)
	{
		List<Activity> monthlyActivities = new ArrayList<Activity>();
		List<Activity> allActivities = getUserActivities(currentUser);
		for (Activity activity: allActivities) {
			if (month == getMonth(activity.getStart()) && controlYear(activity.getStart())) {
				monthlyActivities.add(activity);
			}
		}
		return monthlyActivities;
	}
	
	/**
	 * De activiteiten van alle gebruikers in een opgegeven maand worden weergegeven in een lijst.
	 * 
	 * @param monthNumber (rekening houden met oktober is 0, november 1, ..., september 11)
	 * @return Lijst met de activiteiten van alle users van de opgegeven maand.
	 */
	public static List<Activity> getAllMonthlyActivities(int month)
	{
		List<Activity> monthlyActivities = new ArrayList<Activity>();
		List<Activity> allActivities = getAllUsersActivities();
		for (Activity activity: allActivities) {
			if (month == getMonth(activity.getStart()) && controlYear(activity.getStart())) {
				monthlyActivities.add(activity);
			}
		}
		return monthlyActivities;	
	}

	/**
	 * De totaal gespendeerde tijd aan een opgegeven vak van een opgegeven gebruiker wordt weergegeven.
	 * 
	 * @param user
	 * @param courseId
	 * @return Totale tijd gespendeerd aan het opgegeven vak door de opgegeven user.
	 */
	public static double getCourseDurationUser(User user,long courseId) 
	{
		double total=0;
		List<Activity> activities = user.getActivities();
		for(Activity activity: activities){
			if (controlYear(activity.getStart())) {
				if (activity.getCourseId() == courseId) {
					total = total + activity.getDuration();		
				}
			}
		}
		double totalHour = total/3600;
		return totalHour;
	}

	/**
	 * Deze methode vergelijkt de inspanningen van een opgegeven gebruiker voor een opgegeven vak ten opzichte van 
	 * alle gebruikers.
	 * 
	 * @param user
	 * @param courseId
	 * @return Het percentage gebruikers dat minder of evenveel tijd gespendeerd heeft aan het opgegeven vak 
	 * dan de opgegeven gebruiker.
	 */
	public static double getPositionOfCourseStudyTime(User user, long courseId)
	{
		double before = 0;
		double after = 0;
		double userTime = getCourseDurationUser(user, courseId);
		for(User u: UserRegistry.getInstance().getAllUsers())
		{
			if(getCourseDurationUser(u, courseId) < userTime)
				before = before + 1.0;
			else
				after = before + 1.0;
		}

		return ((before/(before + after)) * 100);
	}
	
	public static double getPositionTotal(User user)
	{
		double before = 0;
		double after = 0;
		double userTime = getTotalDuration(user, user);
		for(User u: UserRegistry.getInstance().getAllUsers())
		{
			if(getTotalDuration(u, u) < userTime)
				before += 1.0;
			else
				after +=1.0;
		}
		
		return ((before/(before + after)) * 100);
	}

	/**
	 * De tijd dat een opgegeven gebruiker al gespendeerd heeft aan de vakken die de huidige gebruiker ook volgt wordt
	 * weergegeven in een map.
	 * 
	 * @param user waarvan de gespendeerde tijd gevraagd is
	 * @param currentUser waarvan de vakken opgehaald worden
	 * @return Map met als key de courseName (van de huidige gebruiker) en als value het aantal uur dat de opgegeven user 
	 * al aan dat vak heeft gewerkt.
	 */
	public static Map<String, Double> getTotalDurationPerCourse(User user, User currentUser)
	{
		Map<String,Double> courseDurations = new LinkedHashMap<String,Double>();
		List<Long> courseIds = new ArrayList<Long>();
		courseIds = currentUser.getCourses();
		for (Long courseId : courseIds) {
			double duration = getCourseDurationUser(user,courseId);
			String courseName = CourseRegistry.getInstance().getCourseName(courseId);
			courseDurations.put(courseName, duration);
		}
		return courseDurations;
	}

	/**
	 * De tijd dat alle gebruikers al gespendeerd hebben aan de vakken die de huidige gebruiker volgt wordt
	 * weergegeven in een map.
	 * 
	 * @param currentUser
	 * @return Map met als key de courseName (van de huidige gebruiker) en als value het aantal uur dat alle users al 
	 * aan dat vak hebben gewerkt.
	 */
	public static Map<String, Double> getTotalDurationCoursesAllUsers(User currentUser)
	{
		Map<String,Double> totalDurations = new LinkedHashMap<String,Double>();
		List<Long> courseIds = currentUser.getCourses();
		for(long courseId: courseIds){
			String courseName=CourseRegistry.getInstance().getCourseName(courseId);
			totalDurations.put(courseName, 0.0);
		}
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			Map<String, Double> durationPercourse = getTotalDurationPerCourse(user, currentUser);
			Iterator it = durationPercourse.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry pairs = (Map.Entry)it.next();
				double value  = (Double) pairs.getValue();
				String key = (String) pairs.getKey();
				double newValue =totalDurations.get(key)+value;
				totalDurations.put(key,newValue);
			}
		}
		return totalDurations;
	}

	/**
	 * De gemiddelde tijd dat de opgegeven gebruiker al gespendeerd heeft aan zijn verschillende vakken wordt
	 * weergegeven in een map.
	 * 
	 * @param currentUser
	 * @return Map met als key de courseName (van de huidige gebruiker) en als value het gemiddeld aantal uur dat 
	 * de opgegeven gebruiker al aan dat vak heeft gewerkt.
	 */
	public static Map<String, Double> getAverageDurationPerCourse(User currentUser)
	{
		Map<String,Double> totalDurations = new LinkedHashMap<String,Double>();
		Map<String, Double> result= new LinkedHashMap<String, Double>();
		LinkedHashMap<String, Integer> count = new LinkedHashMap<String, Integer>();
		List<Long> courseIds = new ArrayList<Long>();
		courseIds = currentUser.getCourses();
		// vullen met 0
		for (Long courseId : courseIds) {
			String courseName = CourseRegistry.getInstance().getCourseName(courseId);
			totalDurations.put(courseName, 0.0);
			count.put(courseName,0);
		}
		List<User> users = UserRegistry.getInstance().getAllUsers();	
		//Maken LinkedHashMap met Vak + TOTALE TIJD
		for (User user : users) {
			Map<String, Double> durationPercourse = getTotalDurationPerCourse(user, currentUser);
			Iterator it = durationPercourse.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry pairs = (Map.Entry)it.next();
				double value  = (Double) pairs.getValue();
				String key = (String) pairs.getKey();
				double newValue =totalDurations.get(key)+value;
				int newCount = count.get(key)+1;
				totalDurations.put(key,newValue);
				count.put(key, newCount);	
			}	
		}
		// Delen door juiste aantal => LinkedHashMap met VAK + gemiddelde tijd
		Iterator it2 = totalDurations.entrySet().iterator();
		while (it2.hasNext()) {
			Map.Entry pairs = (Map.Entry)it2.next();
			double value  = (Double) pairs.getValue();
			String key = (String) pairs.getKey();
			if(count.get(key)!=0){
				result.put(key, value/count.get(key));
			}
			else{
				result.put(key,0.0);
			}
		}
		return result;
	}

	/**
	 * De vakken van de opgegeven gebruiker met de bijhorende studiepunten worden weergegeven in een map.
	 * 
	 * @param currentUser
	 * @return Map met als key de courseName en als value de studiepunten van datzelfde vak.
	 */
	public static Map<String,Integer> getStudyPointsCourses(User currentUser)
	{
		Map<String,Integer> studyPoints = new LinkedHashMap<String,Integer>();
		List<Long> courseIds = new ArrayList<Long>();
		courseIds = currentUser.getCourses();
		for (Long courseId : courseIds) {
			String courseName = CourseRegistry.getInstance().getCourseName(courseId);
			int studyPoint = CourseRegistry.getInstance().getCourseByName(courseName).getStudyPoints();
			studyPoints.put(courseName, studyPoint);
		}
		return studyPoints;
	}

	/**
	 * Deze methode geeft de totale tijd dat een opgegeven gebruiker al gespendeerd heeft aan de vakken die de 
	 * huidige gebruiker ook volgt.
	 * 
	 * @param user waarvan de totale tijd gevraagd is
	 * @param currentUser waarvan de vakken gebruikt worden
	 * @return Totale duur dat de opgegeven user al aan vakken van de currentuser gespendeerd heeft.
	 */
	public static double getTotalDuration(User user, User currentUser)
	{
		Map<String, Double> durationPerCourse = getTotalDurationPerCourse(user, currentUser);
		@SuppressWarnings("rawtypes")
		Iterator it2 = durationPerCourse.entrySet().iterator();
		double result=0;
		while (it2.hasNext()) {
			@SuppressWarnings("rawtypes")
			Map.Entry pairs = (Map.Entry)it2.next();
			double value  = (Double) pairs.getValue();
			result=value+result;
		}
		return result;
	}

	/**
	 * De totale tijd dat elke gebruiker gespendeerd heeft wordt weergegeven in een map.
	 * 
	 * @return Map met userName van elke user als value en de totaal gespendeerde tijd van de bijhorende user als value.
	 */
	public static Map<String,Double> getTotalDurationUsers()
	{
		LinkedHashMap<String,Double> result = new LinkedHashMap<String,Double>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			result.put(user.getUserName(),getTotalDuration(user, user));
		}
		return result;
	}

	/**
	 * De vakken van de opgegeven gebruiker met de respectievelijke gemiddelde appreciatie worden in een map weergegeven.
	 * 
	 * @param currentUser
	 * @return Map met vakken van de opgegeven gebruikers als keys en gemiddelde appreciatie van het desbetreffende vak van
	 * de opgegeven gebruiker.
	 */
	public static Map<String, Double> getAverageAppreciationPerCourse(User currentUser){
		Map<String, Double> result = new LinkedHashMap<String, Double>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		List<Long> courseIds = currentUser.getCourses();

		for(Long courseId : courseIds){
			double appreciation = 0.0;
			double count = 0.0;
			for(User user : users){
				List<Activity> activities = user.getActivities();
				for(Activity activity : activities){
					if(controlYear(activity.getStart()) && activity.getCourseId()==courseId){
						appreciation = appreciation + activity.getAppreciation();
						count++;
					}
				}

			}
			result.put(CourseRegistry.getInstance().getCourseName(courseId), appreciation/count);
		}


		return result;
	}
	
	/**
	 * De vakken van de opgegeven gebruiker met de respectievelijke gemiddelde appreciaties van de opgegeven gebruiker.
	 * 
	 * @param user
	 * @param currentUser
	 * @return Map met als key de courseName en als value de gemiddelde appreciatie van de user voor alle activiteiten van dat vak.
	 */
	public static Map<String,Double>getUserAppreciationPerCourse(User user, User currentUser)
	{
		Map<String,Double> appreciation = new LinkedHashMap<String,Double>();
		List<Activity> activities = new ArrayList<Activity>();
		activities = user.getActivities();
	
		List<Long> courseIds = currentUser.getCourses();

		for(Long courseId : courseIds){
			double total=0.0;
			appreciation.put(CourseRegistry.getInstance().getCourseName(courseId),0.0);
			int i=0;
			for(Activity activity: activities){
				if (controlYear(activity.getStart())) {
					if (activity.getCourseId() == courseId) {
						total=activity.getAppreciation()+total;
						i++;
					}
				}
			}
			if (i!=0) {
			appreciation.put(CourseRegistry.getInstance().getCourseName(courseId), (total/i));
			}

		}
		return appreciation;
	}

	/**
	 * De vakken van de opgegeven gebruiker met het respectievelijk aantal studiepunten worden weergegeven in een map.
	 * 
	 * @param user
	 * @return Map met als key de courseName en als value de studiepunten horende bij die Course.
	 */
	public static Map<String, Double> getStudyPointsPerCourse(User user)
	{
		LinkedHashMap<String, Double> studyPoints = new LinkedHashMap<String, Double>();
		List<Long> courseIds = new ArrayList<Long>();
		courseIds = user.getCourses();
		for (Long courseId : courseIds) {
			String courseName = CourseRegistry.getInstance().getCourseName(courseId);
			double studyPoint = CourseRegistry.getInstance().getCourseByName(courseName).getStudyPoints();
			studyPoints.put(courseName, studyPoint);
		}
		return studyPoints;
	}

	/**
	 * Deze methode retourneert de totale tijd gespendeerd door de opgegeven gebruiker aan het opgegeven type van het 
	 * opgegeven vak.
	 * 
	 * @param courseName
	 * @param user
	 * @param currentUser
	 * @param type
	 * @return De totale tijd gespendeerd door de opgegeven gebruiker aan het opgegeven type van het opgegeven vak.
	 */
	public static double getTypeDurationUserPerCourse(String courseName, User user, User currentUser, String type) 
	{
		double total = 0;

		List<Activity> activities = getUserActivities(user);
		for(Activity activity : activities){
			if(activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName) && controlYear(activity.getStart())){
				if (activity.getType().equals(type)) {
					total = total + activity.getDuration();
				}
			}
		}
		double totalHour = total/3600;
		return totalHour;
	}

	/**
	 * De verschillende types van activiteiten (lecture, worksession, studying, other) met de respectievelijk totale tijd
	 * gespendeerd aan het opgegeven vak door de opgegeven gebruiker.
	 * 
	 * @param courseName
	 * @param user
	 * @param currentUser
	 * @return Map met de verschillende types van activiteiten (lecture, worksession, studying, other) als keys en de 
	 * respectievelijk totale tijd gespendeerd aan het opgegeven vak door de opgegeven gebruiker als values.
	 */
	public static Map<String, Double> getTotalDurationPerType(String courseName, User currentUser) 
	{
		Map<String,Double> totalDurations = new LinkedHashMap<String,Double>();
		List<String> types = new ArrayList<String>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		double duration = 0.0;
		types.add("Lecture");
		types.add("Worksession");
		types.add("Studying");
		types.add("Other");
		for(String type: types){
			duration=0.0;
			for (User user: users) {
				duration = duration + getTypeDurationUserPerCourse(courseName, user, currentUser, type);
			}
			totalDurations.put(type, duration);
		}
		return totalDurations;
	}
	
	public static Map<String, Double> getUserDurationPerType(String courseName, User currentUser){
		Map<String, Double> durationMap = new LinkedHashMap<String, Double>();
		List<String> types = new ArrayList<String>();
		types.add("Lecture");
		types.add("Worksession");
		types.add("Studying");
		types.add("Other");
		for(String type: types){
			double duration = getTypeDurationUserPerCourse(courseName, currentUser, currentUser, type);
			durationMap.put(type, duration);
		}
		return durationMap;
	}
	/**
	 * Deze methode retourneert de totale tijd gespendeerd door de opgegeven gebruiker voor het opgegeven vak 
	 * tijdens het opgegeven interval.
	 * 
	 * @param courseName
	 * @param interval (week, month, year)
	 * @param user
	 * @return Totale tijd gespendeerd door de opgegeven gebruiker voor het opgegeven vak tijdens het opgegeven interval.
	 */
	public static double getTotalTime(String courseName, String interval, User user) {
		double time = 0.0;		
		Date now = new Date();
		if(interval.equals("week")){
			List<Activity> monthlyActivities = new ArrayList<Activity>();
			int month = getMonth(now);
			monthlyActivities = getMonthlyActivitiesUser(user, month);
			for (Activity activity: monthlyActivities) {
				if (controlWeek(activity.getStart())) {
					time = time + activity.getDuration();
				}
			}
		}
		else if(interval.equals("month")){
			List<Activity> monthlyActivities = new ArrayList<Activity>();
			int month = getMonth(now);
			monthlyActivities = getMonthlyActivitiesUser(user, month);
			time=0.0;
			for (Activity activity: monthlyActivities) {
				if (controlYear(activity.getStart())) {
					time = time + activity.getDuration();
				}
			}
		}
		else if(interval.equals("year")){
			time=0.0;
			List<Activity> userActivities = new ArrayList<Activity>();
			userActivities = getUserActivities(user);
			for (Activity activity: userActivities) {
				if (controlYear(activity.getStart())) {
					time = time + activity.getDuration();
				}
			}
		}
		time = time/3600;
		return time;
	}
	
	/**
	 * De verschillende tijdsintervallen (week, month, year) met de respectieve totale tijd gespendeerd door 
	 * alle gebruikers voor het opgegeven vak.
	 * 
	 * @param courseName
	 * @return Map met verschillende tijdsintervallen (week, month, year) als keys en bijhorende totale tijd gespendeerde tijd
	 * door alle gebruikers voor het opgegeven vak als value.
	 */
	public static Map<String, Double> getUserDurationPerInterval(String courseName) {
		Map<String,Double> durationsPerInterval = new LinkedHashMap<String,Double>();
		List<String> intervals = new ArrayList<String>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		double duration = 0.0;
		intervals.add("week");
		intervals.add("month");
		intervals.add("year");
		for(String interval: intervals) {
			for(User user: users) {
				duration = duration + getTotalTime(courseName, interval, user);	
			}
			duration = duration/users.size();
			durationsPerInterval.put(interval, duration/3600);
		}
		return durationsPerInterval;
	}

	/**
	 * De weekdagen met het respectievelijk aantal uur getimed voor het opgegeven vak door de opgegeven gebruiker.
	 * 
	 * @param courseName
	 * @param currentUser
	 * @return Map met als key de weekdag en als value het aantal uur dat er door de currentUser getimed is op die dag.
	 */
	public static Map<String,Double> getTimeOfUserPerWeek(String courseName, User currentUser)
	{
		Map<String, Double> durationPerDayCurrentUser = new LinkedHashMap<String, Double>();
		Date today = new Date();
		int end = getDay(today);
		int start = 0;
		double durationPerDay=0.0;
		List<String> days = new ArrayList<String>();
		days.add(0, "Sunday");
		days.add(1, "Monday");
		days.add(2, "Tuesday");
		days.add(3, "Wednesday");
		days.add(4, "Thursday");
		days.add(5, "Friday");
		days.add(6, "Saturday");
		

		for (int i=start; i<=end;i++){
			durationPerDayCurrentUser.put(days.get(i), 0.0);
		}

		for(int i= start; i<=end;i++){
			List<Activity> activities = getDailyActivitiesUser(currentUser,i);	
			durationPerDay=0.0;
			for(Activity activity : activities){
	
				if(activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName)){
					durationPerDay = activity.getDuration()+durationPerDay;
				}
			}
			durationPerDayCurrentUser.put(days.get(i), durationPerDay/3600);
		}
		return durationPerDayCurrentUser;
	}

	/**
	 * De weekdagen met het respectievelijk aantal uur getimed voor het opgegeven vak door alle gebruikers.
	 * 
	 * @param courseName
	 * @return Map met als key de weekdag en als value het aantal uur dat er door alle users getimed is op die dag.
	 */
	public static Map<String,Double> getTimeOfAllUsersPerWeek(String courseName)
	{
		Map<String, Double> durationPerDayAllUsers = new LinkedHashMap<String, Double>();
		Date today = new Date();
		int end = getDay(today);
		int start = 0;
		double durationPerDay=0;
		List<String> days = new ArrayList<String>();
	
		days.add(0, "Sunday");
		days.add(1, "Monday");
		days.add(2, "Tuesday");
		days.add(3, "Wednesday");
		days.add(4, "Thursday");
		days.add(5, "Friday");
		days.add(6, "Saturday");

		for (int i=start; i<=end;i++){
			durationPerDayAllUsers.put(days.get(i), 0.0);
		}

		for(int i= start; i<=end;i++){
			durationPerDay=0.0;
			List<Activity> activities = getAllDailyActivities(i);
			for(Activity activity : activities){
				if(activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName)){
					durationPerDay = activity.getDuration() + durationPerDay;
				}
			}
			durationPerDayAllUsers.put(days.get(i), durationPerDay/3600);
		}
		return durationPerDayAllUsers;
	}

	/**
	 * Deze methode geeft voor een datum het equivalente nummer.
	 * 
	 * @param start
	 * @return Dagnummer: maandag is 1, dinsdag 2,..., zondag is 7.
	 */
	public static int getDay(Date start)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(start);
		int day = calendar.get(Calendar.DAY_OF_WEEK);
		if (day == 0) {
			day = day + 6;
		}
		else {
			day = day-1;
		}
		return day;
	}

	/**
	 * Methode controleert of de opgegeven activiteit binnen de huidige week valt.
	 * 
	 * @param start
	 * @return true indien de activiteit binnen de huidige week valt, false indien dit niet het geval is.
	 */
	public static boolean controlWeek(Date start)
	{
		boolean control;
		Calendar calendar = Calendar.getInstance();
		Date now = new Date();
		calendar.setTime(now);
		int thisWeek = calendar.get(Calendar.WEEK_OF_YEAR);
		calendar.setTime(start);		
		int weekOfActivity = calendar.get(Calendar.WEEK_OF_YEAR);
		if (thisWeek != weekOfActivity) {
			control = false;
		}
		else {
			control = true;
		}
		return control;
	}

	/**
	 * Een lijst met de activiteiten van een opgegeven gebruiker op een opgegeven weekdag wordt weergegeven.
	 * 
	 * @param currentUser
	 * @param day (maandag is 0,..., zondag is 6)
	 * @return Lijst met alle activiteiten van de currentUser op de opgegeven weekdag.
	 */
	public static List<Activity> getDailyActivitiesUser(User currentUser, int day)
	{
		List<Activity> dailyActivities = new ArrayList<Activity>();
		List<Activity> allActivities = getUserActivities(currentUser);
		for (Activity activity: allActivities) {
			if (day == getDay(activity.getStart()) && controlWeek(activity.getStart()) && controlYear(activity.getStart())) {
				dailyActivities.add(activity);
			}
		}
		return dailyActivities;
	}

	/**
	 * Een lijst met de activiteiten van een opgegeven gebruiker op een opgegeven dag wordt weergegeven.
	 * 
	 * @param currentUser
	 * @param day eerste dag van de maand is 1, de tweede dag is 2,...
	 * @param month oktober is 0, november is 2,...
	 * @return Lijst met alle activiteiten van de currentUser op de opgegeven dag.
	 */
	public static List<Activity> getSpecificDailyActivitiesUser(User currentUser, int day, int month)
	{
		List<Activity> dailyActivities = new ArrayList<Activity>();
		List<Activity> allActivities = getUserActivities(currentUser);
		for (Activity activity: allActivities) {
			if (day == getDayOfMonth(activity.getStart()) && month==getMonth(activity.getStart())) {
				dailyActivities.add(activity);
			}
		}
		return dailyActivities;
	}

	/**
	 * Een lijst met de activiteiten van alle gebruikers op een opgegeven weekdag wordt weergegeven.
	 * 
	 * @param day (parameter met maandag is 0,..., zondag is 6)
	 * @return Lijst met alle activiteiten van alle users op een bepaalde weekdag.
	 */
	public static List<Activity> getAllDailyActivities(int day)
	{
		List<Activity> dailyActivities = new ArrayList<Activity>();
		List<Activity> allActivities = getAllUsersActivities();
		for (Activity activity: allActivities) {
			if (day == getDay(activity.getStart()) && controlWeek(activity.getStart()) && controlYear(activity.getStart())) {
				dailyActivities.add(activity);
			}
		}
		return dailyActivities;	
	}

	/**
	 * Een lijst met de appreciaties van de opgegeven gebruiker voor het opgegeven vak wordt weergegeven.
	 * 
	 * @param courseName
	 * @param currentUser
	 * @return Lijst met de appreciaties van de opgegeven gebruiker voor het opegegeven vak.
	 */
	public static List<Double> getAppreciations(String courseName, User currentUser)
	{
		List<Double> appreciations = new ArrayList<Double>();
		Map<String, Double> appreciationCurrentUser = new LinkedHashMap<String, Double>();
		appreciationCurrentUser = getUserAppreciationPerCourse(currentUser, currentUser);
		double averageAppreciationCurrentUser=0.0;
		averageAppreciationCurrentUser=appreciationCurrentUser.get(courseName);
		appreciations.add(0,averageAppreciationCurrentUser);

		Map<String, Double> appreciationAllUsers = new LinkedHashMap<String, Double>();
		appreciationAllUsers = getAverageAppreciationPerCourse(currentUser);
		double averageAppreciationAllUsers=0.0;
		averageAppreciationAllUsers=appreciationAllUsers.get(courseName);
		appreciations.add(1,averageAppreciationAllUsers);

		return appreciations;
	}

	/**
	 * De maanden met het respectievelijk aantal uur getimed voor het opgegeven vak door de opgegeven gebruiker wordt 
	 * weergegeven in een map.
	 * 
	 * @param courseName
	 * @param currentUser
	 * @return Map met als key de maand en als value het aantal uur getimed in die maand door de currentUser.
	 */
	public static Map<String, Double> getDurationPerMonthCurrentUser(String courseName, User currentUser)
	{
		Map<String, Double> durationPerMonthCurrentUser = new LinkedHashMap<String, Double>();
		Date today = new Date();
		int end = getMonth(today);
		int start = 0;
		double durationPerMonth=0.0;
		List<String> months = getMonthNames();
		List<Activity> activities = new ArrayList<Activity>();
		for (int i=start; i<=end;i++){
			durationPerMonthCurrentUser.put(months.get(i), 0.0);
		}

		for(int i= start; i<=end; i++){
			durationPerMonth=0.0;
			activities = getMonthlyActivitiesUser(currentUser,i);
			for(Activity activity : activities){
				if(controlYear(activity.getStart()) && activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName)){
					durationPerMonth = activity.getDuration() + durationPerMonth;
				}
			}
			durationPerMonthCurrentUser.put(months.get(i), durationPerMonth/3600);
		}
		return durationPerMonthCurrentUser;
	}

	/**
	 * De maanden met het respectievelijk aantal uur getimed voor het opgegeven vak door alle gebruikers wordt 
	 * weergegeven in een map.
	 * 
	 * @param courseName
	 * @return Map met als key de maand en als value het aantal uur getimed in die maand door alle users.
	 */
	public static Map<String, Double> getDurationPerMonthAllUsers(String courseName)
	{
		Map<String, Double> durationPerMonthAllUsers = new LinkedHashMap<String, Double>();
		Date today = new Date();
		int end = getMonth(today);
		int start = 0;
		double durationPerMonth=0;
		List<String> months = getMonthNames();
		List<Activity> activities = new ArrayList<Activity>();
		for (int i=start; i<=end;i++){
			durationPerMonthAllUsers.put(months.get(i), 0.0);
		}

		for(int i= start; i<=end; i++){
			activities = getAllMonthlyActivities(i);
			for(Activity activity : activities){
				if(controlYear(activity.getStart()) && activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName)){
					durationPerMonth = activity.getDuration() + durationPerMonth;
				}
			}
			durationPerMonthAllUsers.put(months.get(i), durationPerMonth/3600);
		}
		return durationPerMonthAllUsers;
	}

	/**
	 * De dagen van de maand met het respectievelijk aantal uur getimed voor het opgegeven vak door de opgegeven gebruiker
	 * wordt weergegeven in een map.
	 * 
	 * @param currentUser
	 * @param courseName
	 * @return Map met als key de dag van de maand en als value het aantal uur getimed op die dag van de maand door de currentUser.
	 */
	public static Map<String, Double> getDurationPerDayThisMonthUser(User currentUser, String courseName)
	{


		Map<String, Double> dailyDurationPerMonthCurrentUser = new LinkedHashMap<String, Double>();
		Map<String, Double> result = new LinkedHashMap<String, Double>();

		double dailyDurationPerMonth=0;
		Date today = new Date();
		int month = getMonth(today);
		List<String> months = getMonthNames();
		List<Activity> activities = new ArrayList<Activity>();
		activities = getMonthlyActivitiesUser(currentUser,month);
		
		for(Activity activity : activities){
			if(activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName)){
				dailyDurationPerMonth = activity.getDuration() + dailyDurationPerMonth;
			}
			dailyDurationPerMonthCurrentUser.put(getDayOfMonth(activity.getStart()) + " " + months.get(month) , dailyDurationPerMonth/3600);
		}
		
		if (month == 4) {
			for (int i=1; i<=28;i++){
				if(dailyDurationPerMonthCurrentUser.containsKey(i + " " + months.get(month))){
				result.put(i + " " + months.get(month), dailyDurationPerMonthCurrentUser.get(i + " " + months.get(month)));
				}
				else{
				result.put(i + " " + months.get(month), 0.0);
				}
			}
		}
		else if (month == 0 || month == 2 || month == 3 || month == 5 || month == 7 || month == 9 || month == 10) {
			for (int i=1; i<=31;i++){
				if(dailyDurationPerMonthCurrentUser.containsKey(i + " " + months.get(month))){
					result.put(i + " " + months.get(month), dailyDurationPerMonthCurrentUser.get(i + " " + months.get(month)));
					}
					else{
					result.put(i + " " + months.get(month), 0.0);
					}
			}
		}
		else if (month == 1 || month == 6 || month == 8 || month == 11) {
			for (int i=1; i<=30;i++){
				if(dailyDurationPerMonthCurrentUser.containsKey(i + " " + months.get(month))){
					result.put(i + " " + months.get(month), dailyDurationPerMonthCurrentUser.get(i + " " + months.get(month)));
					}
					else{
					result.put(i + " " + months.get(month), 0.0);
					}
			}
		}

		return result;
	}

	/**
	 * Zelfde methode als getDurationPerDayThisMonthUser maar herschreven in de hoop dat het zonder fouten werkt
	 * 
	 * @param currentUser
	 * @param courseName
	 * @return
	 */
	public static Map<String, Double> testmethodegetDurationPerDayThisMonthUser(User currentUser, String courseName)
	{
		Map<String, Double> dailyDurationPerMonthCurrentUser = new LinkedHashMap<String, Double>();
		Map<String, Double> result = new LinkedHashMap<String, Double>();

		double dailyDurationPerMonth=0;
		Date today = new Date();
		int month = getMonth(today);
		List<String> months = getMonthNames();
		List<Activity> activities = new ArrayList<Activity>();
		activities = getMonthlyActivitiesUser(currentUser,month);
		
		if (month == 4) {
			for (int i=1; i<=28;i++){
				for(Activity activity : activities){
					if(getDay(activity.getStart()) == i) {
						if (activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName)) {
							dailyDurationPerMonth = activity.getDuration() + dailyDurationPerMonth;
						}
					}
				}
				dailyDurationPerMonthCurrentUser.put(i + " " + months.get(month) , dailyDurationPerMonth/3600);
			}	
		}
		else if (month == 0 || month == 2 || month == 3 || month == 5 || month == 7 || month == 9 || month == 10) {
			for (int i=1; i<=31;i++){
				for(Activity activity : activities){
					if(getDay(activity.getStart()) == i) {
						if (activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName)) {
							dailyDurationPerMonth = activity.getDuration() + dailyDurationPerMonth;
						}
					}
				}
				dailyDurationPerMonthCurrentUser.put(i + " " + months.get(month) , dailyDurationPerMonth/3600);
			}	
		}
		else if (month == 1 || month == 6 || month == 8 || month == 11) {
			for (int i=1; i<=30;i++){
				for(Activity activity : activities){
					if(getDay(activity.getStart()) == i) {
						if (activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName)) {
							dailyDurationPerMonth = activity.getDuration() + dailyDurationPerMonth;
						}
					}
				}
				dailyDurationPerMonthCurrentUser.put(i + " " + months.get(month) , dailyDurationPerMonth/3600);
			}	
		}
		return result;
	}
	
	/**
	 * De dagen van de maand met het respectievelijk aantal uur getimed voor het opgegeven vak door alle gebruikers
	 * wordt weergegeven in een map.
	 * 
	 * @param courseName
	 * @return Map met als key de dag van de maand en als value het aantal uur getimed op die dag van de maand door alle users.
	 */
	public static Map<String, Double> getDurationPerDayPerMonthAllUsers(String courseName)
	{
		Map<String, Double> dailyDurationPerMonthAllUsers = new LinkedHashMap<String, Double>();
		Map<String, Double> result = new LinkedHashMap <String, Double>();
		Date today = new Date();
		int month = getMonth(today);
		double dailyDurationPerMonth=0;
		List<String> months = getMonthNames();
		List<Activity> activities = getAllMonthlyActivities(month);
		for(Activity activity : activities){
			if(activity.getCourseId() == CourseRegistry.getInstance().getCourseId(courseName) && controlYear(activity.getStart())){
				dailyDurationPerMonth = activity.getDuration() + dailyDurationPerMonth;
			}
			dailyDurationPerMonthAllUsers.put(getDayOfMonth(activity.getStart()) + " " + months.get(month), dailyDurationPerMonth/3600);
		}
		
		
		if (month == 4) {
			for (int i=1; i<=28;i++){
				if(dailyDurationPerMonthAllUsers.containsKey(i + " " + months.get(month))){
				result.put(i + " " + months.get(month), dailyDurationPerMonthAllUsers.get(i + " " + months.get(month)));
				}
				else{
				result.put(i + " " + months.get(month), 0.0);
				}
			}
		}
		else if (month == 0 || month == 2 || month == 3 || month == 5 || month == 7 || month == 9 || month == 10) {
			for (int i=1; i<=31;i++){
				if(dailyDurationPerMonthAllUsers.containsKey(i + " " + months.get(month))){
					result.put(i + " " + months.get(month), dailyDurationPerMonthAllUsers.get(i + " " + months.get(month)));
					}
					else{
					result.put(i + " " + months.get(month), 0.0);
					}
			}
		}
		else if (month == 1 || month == 6 || month == 8 || month == 11) {
			for (int i=1; i<=30;i++){
				if(dailyDurationPerMonthAllUsers.containsKey(i + " " + months.get(month))){
					result.put(i + " " + months.get(month), dailyDurationPerMonthAllUsers.get(i + " " + months.get(month)));
					}
					else{
					result.put(i + " " + months.get(month), 0.0);
					}
			}
		}
		return result;
	}

	/**
	 * De dag van een opgegeven datum wordt weergegeven. 
	 * 
	 * @param start datum
	 * @return Dag van de maand, bijvoorbeeld 1 of 15 of 28 (max 31).
	 */
	public static int getDayOfMonth(Date start)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(start);
		int day = calendar.get(Calendar.DAY_OF_MONTH);
		return day;
	}

	/**
	 * Deze methode geeft de totale getimede tijd van alle gebruikers voor een opgegeven vak.
	 * 
	 * @param courseID
	 * @return Totale getimede tijd van alle gebruikers voor een opgegeven vak.
	 */
	public static double getCourseDurationAllUsers(long courseID){
		double total=0;
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			total = total + getCourseDurationUser(user, courseID);
		}
		return total;
	}
	
	/**
	 * Deze methode geeft de totale getimede tijd van alle gebruikers.
	 * 
	 * @return Totaal getimede tijd van alle gebruikers.
	 */
	public static double getTotalDurationAllUsers(){
		double total=0;
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			total = total + getTotalDuration(user, user);
		}
		return total;
	}

	/**
	 * Deze methode geeft het aantal pagina's van een opgegeven vak van de opgegeven gebruiker.
	 * 
	 * @param currentuser de huidige gebruiker
	 * @param courseName het vak waarvoor je het aantal pagina's wil weten
	 * @return Het aantal pagina's van een opgegeven vak van de opgegeven gebruiker.
	 */
	public static double getCoursePagesPerUser(User currentuser, String courseName){
		double totalNrOfPages = 0.0;
		List<Activity> activities = currentuser.getActivities();
		for(Activity activity : activities){
			if(activity.getCourseId()==CourseRegistry.getInstance().getCourseId(courseName)){
				if (controlYear(activity.getStart())) {
					totalNrOfPages= totalNrOfPages + activity.getNrOfPages();
				}
			}
		}
		return totalNrOfPages;
	}

	/**
	 * Alle gebruikers met hun respectievelijk totaal aantal pagina's gestudeerd voor een opgegeven vak worden in een map
	 * weergegeven.
	 * 
	 * @param courseName
	 * @return Map met gebruikersnaam van alle gebruikers als keys en bijhorend totaal aantal pagina's gestudeerd van een 
	 * opgegeven vak als value.
	 */
	public static Map<String, Double> getTotalPagesByUserOfCourse(String courseName){
		Map<String, Double> result = new LinkedHashMap<String, Double>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			result.put(user.getUserName(),getCoursePagesPerUser(user,courseName));
		}
		return result;
	}

	/**
	 * Deze methode retourneert het aantal pagina's van een opgegeven vak van alle gebruikers.
	 * 
	 * @param courseName: het vak waarvoor je het aantal pagina's wil weten
	 * @return Het aantal pagina's van een opgegeven vak van alle gebruikers.
	 */
	public static double getCoursePagesAllUsers(String courseName){
		double totalNrOfPages = 0;
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			totalNrOfPages = totalNrOfPages + getCoursePagesPerUser(user, courseName);
		}
		return totalNrOfPages;
	}

	/**
	 * Deze methode retourneert het aantal pagina's van alle vakken van de opgegeven gebruiker.
	 * 
	 * @param currentuser de huidige gebruiker
	 * @return Het aantal pagina's van alle vakken van de opgegeven gebruiker.
	 */
	public static double getPagesAllCoursesPerUser(User currentuser){
		double totalNrOfPages = 0.0;
		List<Long> courseIDs = currentuser.getCourses();
		for(Long courseID : courseIDs){
			totalNrOfPages = totalNrOfPages + getCoursePagesPerUser(currentuser, CourseRegistry.getInstance().getCourseName(courseID));
		}
		return totalNrOfPages;
	}

	/**
	 * Deze methode retourneert het aantal pagina's van alle vakken van alle gebruikers.
	 * 
	 * @return Het aantal pagina's van alle vakken van alle gebruikers.
	 */
	public static double getPagesAllCoursesAllUsers(){
		double totalNrOfPages = 0.0;
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			totalNrOfPages = totalNrOfPages + getPagesAllCoursesPerUser(user);
		}
		return totalNrOfPages;
	}

	/**
	 * Alle gebruikers met hun respectievelijk totaal aantal pagina's gestudeerd worden in een map weergegeven.
	 * 
	 * @return Map met gebruikersnaam van alle gebruikers als keys en bijhorend totaal aantal pagina's gestudeerd als value.
	 */
	public static Map<String, Double> getTotalPagesByUser(){
		Map<String, Double> result = new LinkedHashMap<String, Double>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			result.put(user.getUserName(),getPagesAllCoursesPerUser(user));
		}
		return result;
	}

	/**
	 * Deze methode geeft de verhouding (Aantal pagina's)/(Aantal uren) van een opgegeven vak voor de opgegeven gebruiker.
	 * 
	 * @param currentuser de huidige gebruiker
	 * @param courseName het vak waarvoor je de ratio wil
	 * @return Verhouding (Aantal pagina's)/(Aantal uren) van een opgegeven vak voor de opgegeven gebruiker.
	 */
	public static double getRatioPagesPerDurationCourse(User currentuser, String courseName){
		double ratio = 0;
		double nrOfPages = getCoursePagesPerUser(currentuser, courseName);
		double duration = getCourseDurationUser(currentuser, CourseRegistry.getInstance().getCourseId(courseName));
		if(nrOfPages!=0 || duration!=0){
		ratio = nrOfPages/duration;
		}
		return ratio;
	}

	/**
	 * Alle gebruikers met hun respectievelijke verhouding (Aantal pagina's)/(Aantal uren) van het opgegeven vak worden 
	 * weergegeven in een map.
	 * 
	 * @param courseName
	 * @return Map met username van alle gebruikers als keys en bijhorende verhouding(Aantal pagina's)/(Aantal uren) van het
	 *  opgegeven vak als value.
	 */
	public static Map<String, Double> getTotalRatioByUserOfCourse(String courseName){
		Map<String, Double> result = new LinkedHashMap<String,Double>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			result.put(user.getUserName(),getRatioPagesPerDurationCourse(user, courseName));
		}
		return result;
	}

	/**
	 * Deze methode geeft de verhouding (Aantal pagina's)/(Aantal uren) van een opgegeven vak voor alle gebruikers.
	 * 
	 * @param courseName het vak waarvoor je de ratio wil
	 * @return Verhouding (Aantal pagina's)/(Aantal uren) van een bepaald vak voor alle gebruikers.
	 */
	public static double getRatioPagesPerDurationCourseAllUsers(String courseName){
		double ratio = 0;
		double nrOfPages = getCoursePagesAllUsers(courseName);
		double duration = getCourseDurationAllUsers(CourseRegistry.getInstance().getCourseId(courseName));
		ratio = nrOfPages/duration;
		return ratio;
	}

	/**
	 * Deze methode geeft de verhouding (Aantal pagina's)/(Aantal uren) van alle vakken voor de opgegeven gebruiker.
	 * 
	 * @param currentuser de huidige gebruiker
	 * @return Verhouding (Aantal pagina's)/(Aantal uren) van alle vakken voor de opgegeven gebruiker.
	 */
	public static double getRatioPagesPerDurationAllCourses(User currentuser){
		double ratio = 0;
		double nrOfPages = getPagesAllCoursesPerUser(currentuser);
		double duration = getTotalDuration(currentuser, currentuser);
		if(duration!=0 && nrOfPages!=0){
		ratio = nrOfPages/duration;
		}
		return ratio;
	}

	/**
	 * Alle gebruikers met hun respectievelijke verhouding (Aantal pagina's)/(Aantal uren) van alle vakken worden weergegeven
	 * in een map.
	 * 
	 * @return Map met gebruikersnaam van alle gebruikers als key en de verhouding (Aantal pagina's)/(Aantal uren) van 
	 * alle vakken van de bijhorende gebruiker als value.
	 */
	public static Map<String, Double> getTotalRatioByUser(){
		Map<String, Double> result = new LinkedHashMap<String,Double>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		for (User user : users) {
			result.put(user.getUserName(),getRatioPagesPerDurationAllCourses(user));
		}
		return result;
	}

	/**
	 * Deze methode geeft de verhouding (Aantal pagina's)/(Aantal uren) van alle vakken voor alle gebruikers.
	 * 
	 * @return Verhouding (Aantal pagina's)/(Aantal uren) van alle vakken voor alle gebruikers.
	 */
	public static double getRatioPagesPerDurationAllCoursesAllUsers(){
		double ratio = 0;
		double nrOfPages = getPagesAllCoursesAllUsers();
		double duration = getTotalDurationAllUsers();
		ratio = nrOfPages/duration;
		return ratio;
	}

	/**
	 * Deze methode genereert een lijst met alle dagen van de opgegeven maand.
	 * 
	 * @param monthName
	 * @return List met alle dagen van de opgegeven maand.
	 */
	public static List<String> getCats(String monthName)
	{
		List<String> cats = new ArrayList<String>();
		int month = getMonthNumber(monthName);
		if (month == 4) {
			for (int i=1; i<=28;i++){
				cats.add(i-1, i + " " + monthName);
			}
		}
		else if (month == 0 || month == 2 || month == 3 || month == 5 || month == 7 || month == 9 || month == 10) {
			for (int i=1; i<=31;i++){
				cats.add(i-1, i + " " + monthName);
			}
		}
		else if (month == 1 || month == 6 || month == 8 || month == 11) {
			for (int i=1; i<=30;i++){
				cats.add(i-1, i + " " + monthName);
			}
		}

		return cats;
	}

	/**
	 * Deze methode genereert een lijst met alle maandnamen.
	 * 
	 * @return List met alle maandnamen.
	 */
	public static List<String> getMonthNames()
	{
		List<String> months = new ArrayList<String>();
		months.add(0, "October");
		months.add(1, "November");
		months.add(2, "December");
		months.add(3, "January");
		months.add(4, "February");
		months.add(5, "March");
		months.add(6, "April");
		months.add(7, "May");
		months.add(8, "June");
		months.add(9, "July");
		months.add(10, "August");
		months.add(11, "September");

		return months;
	}

	/**
	 * Deze methode zet een maandnaam om in het equivalente nummer.
	 * 
	 * @param monthName
	 * @return het nummer horend bij een opgegeven maand: 0 is Oktober, 1 is November,...,
	 * 3 is Januari, 4 is Februari,..., 11 is September.
	 */
	public static int getMonthNumber(String monthName){
		Map<String, Integer> monthNumbers = new LinkedHashMap<String, Integer>();
		List<String> months = getMonthNames();
		for(int i = 0; i<12; i++){
			monthNumbers.put(months.get(i), i);
		}
		return monthNumbers.get(monthName);
	}

	/**
	 * De types van een activiteit (lecture, worksession, studying, other) en een bijhorende array met voor alle dagen van 
	 * de opgegeven maand de gespendeerde tijd door de opgegeven gebruiker wordt in een map weergegeven.
	 * 
	 * @param user
	 * @param monthName
	 * @return Map met types van activiteiten (lecture, worksession, studying, other) als key en een array met voor elke dag
	 * van de opgegeven maand de tijd gespendeerd door de opgegeven gebruiker aan het desbetreffende type.
	 */
	public static Map<String, Double[]> getUserMonthMap(User user, String monthName)
	{
		Map<String, Double[]> userMonthMap = new LinkedHashMap <String, Double[]>();
		List<String> types = new ArrayList<String>();
		List<Activity> dailyActivities = new ArrayList<Activity>();
		List<String> days = getCats(monthName);
		double duration = 0.0;
		if(days.size() != 0){
			
		
			types.add("Lecture");
			types.add("Worksession");
			types.add("Studying");
			types.add("Other");
			for(String type: types){
				Double[] dailyHoursPerType = new Double[days.size()];
				for (int i=0; i<days.size(); i++) {
					duration=0;
					dailyHoursPerType[i] = 0.0;
					dailyActivities = getSpecificDailyActivitiesUser(user, i+1, getMonthNumber(monthName));
					if(dailyActivities.isEmpty()){
					duration = 0;
					}
					else{
					for (Activity activity: dailyActivities) {
						if (activity.getType().equals(type)) {
							duration = duration + activity.getDuration();
						 }
					}
					}
					dailyHoursPerType[i] = duration/3600;
				}
				userMonthMap.put(type, dailyHoursPerType);		
			}
		}
		return userMonthMap;
	}

	/**
	 * De types van een activiteit (lecture, worksession, studying, other) en een bijhorende array met voor alle dagen van 
	 * de opgegeven maand de gemiddeld gespendeerde tijd wordt in een map weergegeven.
	 * 
	 * @param monthName
	 * @return Map met types van activiteiten (lecture, worksession, studying, other) als key en een array met voor elke dag
	 * van de opgegeven maand de gemiddelde tijd gespendeerd door alle gebruikers aan het desbetreffende type.
	 */
	public static Map<String, Double[]> getAverageMonthMap(String monthName)
	{
		Map<String, Double[]> averageMonthMap = new LinkedHashMap <String, Double[]>();
		List<String> types = new ArrayList<String>();
		List<Activity> dailyActivities = new ArrayList<Activity>();
		List<String> days = getCats(monthName);
		double duration = 0.0;
		if(days.size() != 0){
		
		
			List<User> users = UserRegistry.getInstance().getAllUsers();
			types.add("Lecture");
			types.add("Worksession");
			types.add("Studying");
			types.add("Other");
			for(String type: types){
				Double[] dailyHoursPerType = new Double[days.size()];
				for (int i=0; i<days.size(); i++) {
					dailyHoursPerType[i] = 0.0;
					duration=0.0;
					for (User user : users) {
						dailyActivities = getSpecificDailyActivitiesUser(user, i+1, getMonthNumber(monthName));
						for (Activity activity: dailyActivities) {
							if (activity.getType().equals(type)) {
								duration = duration + activity.getDuration();
							}
						}
					}
					dailyHoursPerType[i] = (duration/users.size())/3600;
				}
				averageMonthMap.put(type, dailyHoursPerType);		
			}
		}
		return averageMonthMap;
	}

	/**
	 * Deze methode retourneert het gemiddelde van de duur van activiteiten van een opgegeven vak.
	 * 
	 * @param course
	 * @return gemiddelde van de duur van activiteiten van een opgegeven vak
	 */
	public static long getAverageActivityDuration(Course course){
		List<User> users= UserRegistry.getInstance().getAllUsers();
		long total=0;
		long i=0;
		for(User user: users){
			List<Activity> activities = user.getActivities();
			for(Activity activity: activities){
				if (controlYear(activity.getStart())) {
					if (activity.getCourseId() == course.getId()) {
						total=activity.getDuration()+total;
						i++;
					}
				}
			}
		}
		long mean= total/i/3600;		
		return mean;
	}

	/**
	 * Deze methode retourneert de standaarddeviatie van de duur van activiteiten.
	 * 
	 * @param mean: gemiddelde van de duur van activiteiten
	 * @return standaarddeviatie van de duur van activiteiten
	 */
	public static double getDeviationActivityDuration(long mean){
		List<User> users= UserRegistry.getInstance().getAllUsers();
		double total=0;
		long i=0;
		for(User user: users){

			List<Activity> activities = user.getActivities();
			for(Activity activity: activities){
				double result = (java.lang.Math.pow(activity.getDuration()/3600,2)-java.lang.Math.pow(mean,2));
				total = result + total;
				i++;
			}
		}
		double sigma= Math.sqrt(total/i);		
		return sigma;
	}

	/**
	 * De vakken van de opgegeven gebruiker en hun gemiddelde appreciatie door opgegeven gebruiker in de opgegeven maand 
	 * wordt in een map weergegeven.
	 * 
	 * @param user
	 * @return Map met courseName als key en de gemiddelde appreciatie van dat vak door de opgegeven gebruiker
	 *  in de opgegeven maand.
	 */
	public static Map<String, Double> getUserAppreciationPerMonth(User user, String monthName){
		Map<String, Double> result = new LinkedHashMap<String, Double>();
		int monthNumber = getMonthNumber(monthName);
		List<Activity> activities = getMonthlyActivitiesUser(user, monthNumber);
		List<Long> courseIds = user.getCourses();
		for(long courseId : courseIds){
			String courseName = CourseRegistry.getInstance().getCourseName(courseId);
			double value = 0.0;
			double nrOfAppreciations = 0.0;
			for(Activity activity: activities){
				if(activity.getCourseId()==courseId){
					value= value +activity.getAppreciation();
					nrOfAppreciations++;
				}
			}
			if(nrOfAppreciations!=0){
				result.put(courseName, value/nrOfAppreciations);
			}
			else {
				result.put(courseName, 0.0);
			}
		}
		return result;
	}

	/**
	 * De vakken van de opgegeven gebruiker en hun gemiddelde appreciatie door alle gebruikers wordt in een map weergegeven.
	 * 
	 * @param user
	 * @param monthName
	 * @return Map met courseName als key en de gemiddelde appreciatie van dat vak door alle gebruikers
	 *  in de opgegeven maand.
	 */
	public static Map<String, Double> getAverageAppreciationPerMonth(User user, String monthName){
		Map<String, Double> result = new LinkedHashMap<String, Double>();
		int monthNumber = getMonthNumber(monthName);
		List<Activity> activities = getAllMonthlyActivities(monthNumber);
		List<Long> courseIDs = user.getCourses();
		for(long courseId : courseIDs){
			String courseName = CourseRegistry.getInstance().getCourseName(courseId);
			double value = 0.0;
			double nrOfAppreciations = 0.0;
			for(Activity activity : activities){
				if(activity.getCourseId()==courseId && monthNumber == getMonth(activity.getStart()) && controlYear(activity.getStart())){
					value= value + activity.getAppreciation();
					nrOfAppreciations++;
				}
			}
			if(nrOfAppreciations!=0){
				result.put(courseName, value/nrOfAppreciations);
			}
			else {
				result.put(courseName, 0.0);
			}
		}
		return result;
	}

	/**
	 * Deze methode geeft voor de opgegeven maand het totaal aantal uren gespendeerd van de opgegeven gebruiker en van de
	 * gemiddelde gebruiker, en de gemiddelde tijd per dag, ook voor de opgegeven gebruiker en de gemiddelde gebruiker.
	 * 
	 * @param user
	 * @param monthName
	 * @return Map met als key respectievelijk "Total amount of hours user", "Total amount of hours average", 
	 * "Average time per day user", "Average time per day average" en als value respectievelijk het totaal aantal uur gespendeerd door
	 * de opgegeven gebruiker, het gemiddeld aantal uur gespendeerd door alle gebruikers, de gemiddelde tijd gespendeerd per dag
	 * door de opgegeven gebruiker en de gemiddelde tijd gespendeerd per dag door alle gebruikers, telkens voor de 
	 * opgegeven maand.
	 */
	public static Map<String, Double> getMonthStats(User user, String monthName){
		Map<String, Double> result = new LinkedHashMap<String, Double>();
		int month = getMonthNumber(monthName);

		List<Long> courseIDs = user.getCourses();
		double totalDurationUser = 0;
		for(long courseId: courseIDs){
			String courseName = CourseRegistry.getInstance().getCourseName(courseId);
			if(getDurationPerMonthCurrentUser(courseName,user).get(monthName)!=null){
			totalDurationUser = totalDurationUser + getDurationPerMonthCurrentUser(courseName,user).get(monthName);
			}
		}
		result.put("Total hours spent this month.", totalDurationUser);

		double totalDurationAllUsers = 0.0;
		for(long courseId: courseIDs){
			String courseName = CourseRegistry.getInstance().getCourseName(courseId);
			if(getDurationPerMonthCurrentUser(courseName,user).get(monthName)!=null){
				totalDurationAllUsers = totalDurationAllUsers +1;
				}
		}
		result.put("Average amount of hours spent this month of all the students.", totalDurationAllUsers);

		int nrOfDays = 1;
		Date today = new Date();
		if(month==getMonth(today)){
			nrOfDays= getDayOfMonth(today);
		}
		else if (month == 4) {
			nrOfDays= 28;
		}
		else if (month == 0 || month == 2 || month == 3 || month == 5 || month == 7 || month == 9 || month == 10) {
			nrOfDays= 31;
		}
		else if (month == 1 || month == 6 || month == 8 || month == 11) {
			nrOfDays= 30;
		}
		result.put("Hours/Day", totalDurationUser/nrOfDays);
		result.put("Average Hours/Day of all the students.", totalDurationAllUsers/nrOfDays);
		return result;
	}

	/**
	 * Een map met de types van activiteiten (lecture, worksession, studying, other) en de daaraan bestede tijd door de
	 * opgegeven gebruiker gedurende een opgegeven maand worden weergegeven.
	 * 
	 * @param user
	 * @param monthName
	 * @return Map met type van activiteit (lecture, worksession,studying,other) als key en 
	 * de totale tijd van de opgegeven gebruiker aan dat type besteed als value.
	 */
	public static Map<String, Double> getUserTypeMonth(User user, String monthName) {
		Map<String, Double> amount = new LinkedHashMap<String, Double>();
		List<String> types = new ArrayList<String>();
		List<Activity> monthlyActivities = new ArrayList<Activity>();
		double duration = 0.0;
		types.add("Lecture");
		types.add("Worksession");
		types.add("Studying");
		types.add("Other");
		for(String type: types){
			int monthNumber = getMonthNumber(monthName);
			monthlyActivities = getMonthlyActivitiesUser(user, monthNumber);
			for (Activity activity: monthlyActivities) {
				long courseId = activity.getCourseId();
				duration = duration + getTypeDurationUserPerCourse(CourseRegistry.getInstance().getCourseName(courseId), user, user, type);
			}
			amount.put(type, duration);
		}
		return amount;
	}

	/**
	 * Een map met de types van activiteiten (lecture, worksession, studying, other) en de daaraan gemiddelde bestede tijd 
	 * door alle gebruikers gedurende een opgegeven maand worden weergegeven.
	 * 
	 * @param monthName
	 * @return Map met type van activiteit (lecture, worksession,studying,other) als key en 
	 * de gemiddelde tijd van alle gebruikers aan dat type besteed als value.
	 */
	public static Map<String, Double> getAverageTypeMonth(String monthName){
		Map<String, Double> averageAmount = new LinkedHashMap<String, Double>();
		List<String> types = new ArrayList<String>();
		List<Activity> monthlyActivities = new ArrayList<Activity>();
		List<User> users = UserRegistry.getInstance().getAllUsers();
		double duration = 0.0;
		types.add("Lecture");
		types.add("Worksession");
		types.add("Studying");
		types.add("Other");
		for(String type: types){
			for(User user: users){
				int monthNumber = getMonthNumber(monthName);
				monthlyActivities = getMonthlyActivitiesUser(user, monthNumber);
				for (Activity activity: monthlyActivities) {
					long courseId = activity.getCourseId();
					duration = duration + getTypeDurationUserPerCourse(CourseRegistry.getInstance().getCourseName(courseId), user, user, type);
				}
			}
			averageAmount.put(type, duration/users.size());
		}
		return averageAmount;
	}

}
